import { GetOS } from "../utils/GetOS";
import { Interpolate } from "../utils/Interpolate";
import { EventListener } from "./EventListener";

//
export function TouchControls(object, element) {

    // enable
    this.TOUCH_ENABLED = false;
    this.ANIMATE_ENABLED = false;
    this.AUTOPLAY_ENABLED = false;
    // 执行动画中，是否被手指操作打断
    this.ANIMATE_TOUCH_BREAK = true;
    //
    this.TOUCH_UP_TIME = 0;

    // 缩放参数
    this.SCALE_ENABLED = false;
    this.MIN_SCALE = 0.3;  // 最小缩放值
    this.MAX_SCALE = 5.0;  // 最大缩放值
    this.CURRENT_SCALE = 1.0;  // 当前缩放值
    this.SCALE_SPEED = 0.1;  // 缩放速度

    // update
    this.update = (x, y, z) => {
        // 限制
        x = Math.max(-Math.PI, Math.min(0, x));
        // set
        object.rotation.set(x, y, z);
        //
        this.emit('update', object);
    };

    // 更新缩放
    this.updateScale = (scale) => {
        // 限制缩放范围
        this.CURRENT_SCALE = Math.max(this.MIN_SCALE, Math.min(this.MAX_SCALE, scale));
        // 应用缩放
        object.scale.set(this.CURRENT_SCALE, this.CURRENT_SCALE, this.CURRENT_SCALE);
        //
        this.emit('scale', object);
    };

    // animate
    this.animate = (props, duration, change, complete, touchBreak = true) => {
        // 默认允许打断动画
        this.ANIMATE_TOUCH_BREAK = touchBreak;
        //
        this.ANIMATE_ENABLED = true;
        //
        let sTime = Date.now(), t = 0, diff = 0, timer = null, _props = {};
        //
        const callee = () => {
            // 
            if (!object.visible) return;

            // 手指操作时，打断动画
            if (this.ANIMATE_TOUCH_BREAK && this.TOUCH_ENABLED) {
                this.ANIMATE_ENABLED = false;
                cancelAnimationFrame(timer);
                return;
            }

            //
            t = Date.now() - sTime;
            diff = t / duration;
            _props = {};

            // complete
            if (diff >= 1) {
                //
                this.ANIMATE_ENABLED = false;
                // clear
                cancelAnimationFrame(timer);
                //
                for (let k in props) _props[k] = props[k][1];
                change && change(_props);
                complete && complete(_props);
                return;
            }

            // change
            for (let k in props) {
                _props[k] = Interpolate(props[k][0], props[k][1], diff);
            }
            change && change(_props);
            timer = requestAnimationFrame(callee);
        }
        callee();
    };

    // autoplay
    this.autoplay = (() => {
        //
        let status = false, speed = 1;

        // init
        const init = (autoplay) => {
            // status
            this.autoplay.status = !!autoplay;
            // speed
            if (typeof autoplay === 'number') this.autoplay.speed = autoplay;
            else if (typeof autoplay === 'object') this.autoplay.speed = autoplay.speed;
            //
            return this.autoplay;
        }

        // callee
        let timer = null, offset = 0;
        const callee = () => {
            // 非手动操作 | 非动画中
            if (object.visible && !this.TOUCH_ENABLED && !this.ANIMATE_ENABLED && Date.now() - this.TOUCH_UP_TIME > 3000) {
                offset = (offset + speed / 10) % 360;
                this.update(object.rotation.x, 0, offset * Math.PI / 180);
            }
            timer = requestAnimationFrame(callee);
        };

        //
        return {
            status,
            speed,
            init,
            update: (props) => {
                if (props) speed = props;
                offset = object.rotation.z * (180 / Math.PI);
                return this.autoplay;
            },
            start: () => {
                //
                this.autoplay.stop();
                //
                this.AUTOPLAY_ENABLED = true;
                callee();
                return this.autoplay;
            },
            stop: () => {
                this.AUTOPLAY_ENABLED = false;
                cancelAnimationFrame(timer);
                return this.autoplay;
            }
        };

    })();


    // 手机端
    let isTouch = ['ios', 'android'].indexOf(GetOS()) > -1;
    // down
    let downVertor = new THREE.Vector2();
    // rotation
    let rotationVertor = new THREE.Vector3();
    // 缩放相关
    let pinchStartDistance = 0;
    let pinchStartScale = 1.0;

    //
    const mousedown = (e) => {
        // 
        if (!object.visible) return;

        // 非动画中 | 动画时允许touch操作
        if (!this.ANIMATE_ENABLED || this.ANIMATE_TOUCH_BREAK) {
            //
            if (isTouch && e.touches.length === 2) {
                // 双指操作 - 缩放模式
                this.SCALE_ENABLED = true;
                this.TOUCH_ENABLED = false;
                // 计算初始双指距离
                const touch1 = e.touches[0];
                const touch2 = e.touches[1];
                pinchStartDistance = Math.hypot(
                    touch1.pageX - touch2.pageX,
                    touch1.pageY - touch2.pageY
                );
                pinchStartScale = this.CURRENT_SCALE;
            } else {
                // 单指操作 - 旋转模式
                e = isTouch ? e.changedTouches[0] : e;
                // down
                downVertor.set(e.pageX, e.pageY);
                // rotation origin
                rotationVertor.copy(object.rotation);
                // enable
                this.TOUCH_ENABLED = true;
                this.SCALE_ENABLED = false;
            }
        }
    }
    //
    const mousemove = (e) => {
        if (this.SCALE_ENABLED && isTouch && e.touches.length === 2) {
            // 双指缩放处理
            e.preventDefault();

            // 计算当前双指距离
            const touch1 = e.touches[0];
            const touch2 = e.touches[1];
            const currentDistance = Math.hypot(
                touch1.pageX - touch2.pageX,
                touch1.pageY - touch2.pageY
            );

            // 计算缩放比例
            const scale = pinchStartScale * (currentDistance / pinchStartDistance);

            // 更新缩放
            this.updateScale(scale);

        } else if (this.TOUCH_ENABLED) {
            //
            e.preventDefault();
            //
            e = isTouch ? e.changedTouches[0] : e;
            //
            let x = (downVertor.x - e.pageX),
                y = (downVertor.y - e.pageY);

            // 阻止 click
            if (Math.abs(x) > 5 || Math.abs(y) > 5) {
                element.style.pointerEvents = 'none';
            }

            //
            let rx = y * 0.5 * Math.PI / 180 + rotationVertor.x;
            let rz = x * 0.5 * Math.PI / 180 + rotationVertor.z;

            // update
            this.update(rx, 0, rz);
        }
    };
    //
    const mouseup = (e) => {
        if (this.TOUCH_ENABLED || this.SCALE_ENABLED) {
            this.TOUCH_ENABLED = false;
            this.SCALE_ENABLED = false;
            //
            this.TOUCH_UP_TIME = Date.now();
            // 恢复click事件
            element.style.pointerEvents = null;
            //
            this.autoplay.update();
        }
    };

    // 处理滚轮缩放
    const handleWheel = (e) => {
        if (!object.visible) return;

        e.preventDefault();

        // 获取滚轮方向
        const delta = Math.sign(e.deltaY) * -1;

        // 计算新的缩放值
        const newScale = this.CURRENT_SCALE + (delta * this.SCALE_SPEED);

        // 更新缩放
        this.updateScale(newScale);
    };

    // 手机端
    if (isTouch) {
        element.addEventListener('touchstart', mousedown, { passive: false });
        document.addEventListener('touchmove', mousemove, { passive: false });
        document.addEventListener('touchend', mouseup, { passive: false });
    } else {
        element.addEventListener('mousedown', mousedown, { passive: false });
        document.addEventListener('mousemove', mousemove, { passive: false });
        document.addEventListener('mouseup', mouseup, { passive: false });
        // PC端滚轮事件
        element.addEventListener('wheel', handleWheel, { passive: false });
    }

}

//
TouchControls.prototype = Object.assign(TouchControls.prototype, EventListener.prototype);